package ru.spbu.math.android.cbrf.dataprovider;

import android.util.Log;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import ru.spbu.math.android.cbrf.dataprovider.handlers.YandexDynamicSaxHandler;
import ru.spbu.math.android.cbrf.dataprovider.handlers.YandexSaxHandler;
import ru.spbu.math.android.cbrf.model.Rate;
import ru.spbu.math.android.cbrf.model.StockItem;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class YandexProvider implements IProvider {

    private static final String TAG = "Yandex Provider Exception";

    private static final String URL = "http://news.yandex.ru/quotes/";
    private static final String URL_DINAM = "http://news.yandex.ru/quotes/graph_";
    
    private static Map<Integer, String> resourceWidgetMap = new HashMap<Integer, String>();

    public boolean canGetRateByDate() {
        return true;
    }

    public Rate[] getDynamicRates(StockItem source, StockItem target,
                                  Date since, Date until) {
        if (!isUpdatableNow())
            return null;
        if (!target.getCode().equals("USD"))
            return null;

        List<Rate> rateList = new ArrayList<Rate>();
        rateList = getDynamicYandexData(source, target, since, until);

        Rate[] rateArray = rateList.toArray(new Rate[]{});
        return rateArray;
    }

	public Rate getLatestRate(StockItem source, StockItem target) {
        if (!isUpdatableNow())
            return null;
        if (!target.getCode().equals("USD"))
            return null;

        Log.d(TAG, "Get Latest Rate");
        List<Rate> rateList = new ArrayList<Rate>();
        rateList = getListYandexData(source, target);

        if (rateList == null)
            return null;

        return rateList.get(0);
    }

    public Rate getRate(StockItem source, StockItem target, Date date) {
        if (!isUpdatableNow())
            return null;
        if (!target.getCode().equals("USD"))
            return null;

        Log.d(TAG, "Get Rate");
        List<Rate> rateList = new ArrayList<Rate>();
        rateList = getListYandexData(source, target);

        if (rateList == null)
            return null;

        for (Rate r : rateList) {
            if (r.getDate().equals(date))
                return r;
        }
        return null;
    }

    public boolean isUpdatableNow() {
        try {
            URL url = new URL(URL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.connect();
            Log.d(TAG, "Is Updatable");
            return true;
        } catch (IOException e) {
        	Log.e(TAG, "Isn't update now");
            return false;
        }
    }

    private List<Rate> getListYandexData(StockItem source, StockItem target) {

        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
                    
            URL url = new URL(URL + setId(source.getCode()) + ".xml");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            InputSource courseXml = new InputSource(new InputStreamReader(conn
                    .getInputStream(), "utf-8"));
            YandexSaxHandler handler = new YandexSaxHandler();
            handler.setTarget(target);
            parser.parse(courseXml, handler);
            List<Rate> itemList = handler.getRateItem();
            Log.d(TAG, "Get List Yandex Data");
            return itemList;

        } catch (MalformedURLException e) {
            Log.e(TAG, "MalformedURLException");
        } catch (IOException e) {
            Log.e(TAG, "IOException");
        } catch (SAXException e) {
            Log.e(TAG, "SAXException");
        } catch (ParserConfigurationException e) {
            Log.e(TAG, "ParserConfigurationException");
        }

        return null;
    }
    
    private String setId(String code){
    	if(code == "brent")
    		return "1006";
    	else if(code == "AU")
    		return "10";
    	else if(code == "AL")
    		return "1500";
    	else if(code == "CU")
    		return "1501";
    	else if(code == "NI")
    		return "1502";
    	else if(code == "SN")
    		return "1503";
    	else if(code == "PD")
    		return "1504";
    	else if(code == "PT")
    			return "1505";
    	else if(code == "AG")
    		return "1506";
    	else if(code == "ZN")
    		return "1507";
        return null;
    	
    }

    private List<Rate> getDynamicYandexData(StockItem source,StockItem target, Date since,
			Date until) {

        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();

            URL url = new URL(URL_DINAM + setId(source.getCode()) + ".xml");
            URLConnection conn = url.openConnection();
            
            long dateStart = since.getTime();
            long dateFinish = until.getTime();

            InputSource courseXml = new InputSource(new InputStreamReader(conn
                    .getInputStream(), "utf-8"));
            YandexDynamicSaxHandler handler = new YandexDynamicSaxHandler();
            handler.setTarget(target);
            parser.parse(courseXml, handler);
            List<Rate> itemList = handler.getRateItem(dateStart, dateFinish);
            return itemList;

        } catch (MalformedURLException e) {
            Log.e(TAG, "MalformedURLException");
        } catch (IOException e) {
            Log.e(TAG, "IOException");
        } catch (SAXException e) {
            Log.e(TAG, "SAXException");
        } catch (ParserConfigurationException e) {
            Log.e(TAG, "ParserConfigurationException");
        }

        return null;
	}

}
